package com.hz.house.service.detail;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hz.house.bean.entity.*;
import com.hz.house.bean.vo.*;
import com.hz.house.cache.BuildingDetailCacheService;
import com.hz.house.cache.WxAcctkCacheService;
import com.hz.house.common.DaysIntUtil;
import com.hz.house.common.ResultBean;
import com.hz.house.common.ResultUtil;
import com.hz.house.dao.BuildingDetailMapper;
import com.hz.house.dao.HomePageMapper;
import com.hz.house.enums.BidTypeEnum;
import com.hz.house.enums.PropertyType;
import com.hz.house.enums.SellStateEnum;
import com.hz.house.service.CommonService;
import com.hz.house.service.home.HomePageService;
import com.hz.house.token.CurrentUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import sun.misc.BASE64Decoder;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 楼盘详情页业务
 *
 * @author lfw
 */
@Service
@Slf4j
public class BuildingDetailServiceImpl implements BuildingDetailService {

    @Autowired
    private BuildingDetailMapper detailMapper;

    @Autowired
    private BuildingDetailCacheService cacheService;

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private HomePageService homePageService;

    @Resource
    private HomePageMapper hpm;

    @Resource
    private RestTemplate ribonTemplate;

    @Autowired
    private HomePageService pageService;

    public static String QR_IMG_HOST = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=";

    @Autowired
    private WxAcctkCacheService wxAcctkCacheService;

    @Autowired
    private CommonService commonService;

    public static String customerServiceUrl = "http://house-small-sellman/ms/customer";

    private static String buildingBackGroundUrl = "https://housessmall-dev-index-img-1258778894.cos.ap-chengdu.myqcloud.com/icon/lpxqbj.png";


    //使用set去重保存要被批量同步阅读量额楼盘
    private Set<Integer> bids = new HashSet<>();


    //启动同步线程
    public void startVisitWorker() {
        SynVisitsWorker svw = new SynVisitsWorker();
        Thread t = new Thread(svw);
        t.start();
        log.info("楼盘访问同步线程启动成功");
    }

    //楼盘阅读量同步线程
    private class SynVisitsWorker implements Runnable {

        @Override
        public void run() {
            //20秒一次
            while (true) {

                try {
                    try {
                        Thread.sleep(20000);
                    } catch (InterruptedException e) {
                    }
                    log.info("开始进行阅读量同步");
                    if (bids.size() == 0) {
                        log.info("本次需要同步的楼盘为0");
                        continue;
                    }
                    List<SimpleDataBean> ds = new ArrayList<>();
                    synchronized (bids) {
                        for (Integer id : bids) {
                            SimpleDataBean d = new SimpleDataBean();
                            d.setId(id);
                            Integer v = cacheService.getCachedBuildingVisits(id);
                            if (v == null)
                                continue;
                            d.setVisits(v);
                            ds.add(d);
                        }
                        bids.clear();
                    }
                    //批量同步到数据库
                    if (ds.size() > 0)
                        detailMapper.synVisits(ds);
                    log.info("本次同步访问量成功,同步的楼盘数量为:" + ds.size());
                } catch (Exception e) {
                    log.error("批量同步楼盘访问量到数据库异常", e);
                    e.printStackTrace();
                }
            }
        }

    }


    //增加阅读量
    private void addBuildingVisits(Integer buildingId) {
        //范围随机
        int max = 100;
        int min = 50;
        int x = new Random().nextInt(max - min) + min;
        //lua脚本加访问量
        this.cacheService.addvisits(buildingId, x);
        synchronized (bids) {
            //线程不安全
            bids.add(buildingId);
        }
    }


    /**
     * 查询楼盘的基本信息。先从缓存获取，没有再从数据库拉取
     */
    @Override
    public Object getBuildingBasicInfo(Integer buildingId) {
        if (buildingId == null)
            return ResultUtil.fail("楼盘ID不能为空");
        log.info("楼盘ID:" + buildingId);
        BuildingBasicBean basic = this.cacheService.getCachedBuildingBasicInfo(buildingId);
        if (basic != null) {
            //查询用户是否关注该盘，是否收藏了该盘,如果>0则关注了。
            //懒得缓存了，没时间了
            int isfocus = this.detailMapper.getIsfocus(buildingId, CurrentUser.getCurrentUserId());
            int isCollect = this.detailMapper.getIsCollect("building", buildingId, CurrentUser.getCurrentUserId());
            return ResultUtil.ok(buildData(basic, isfocus, isCollect));
        }


        //如果缓存没有,从数据库查询,并初始化缓存
        basic = this.detailMapper.getBaseInfo(buildingId);
        if (basic == null)
            return ResultUtil.fail("楼盘不存在");
        //地铁信息单独查询
        List<BuildingMatchBean> subways = this.detailMapper.getSubwayInfo(buildingId);
        //构造地铁数据
        String[] sbs = new String[subways.size()];
        if (subways.size() > 0) {
            for (int i = 0; i < subways.size(); i++) {
                BuildingMatchBean bm = subways.get(i);
                sbs[i] = (bm.getState() == 0 ? "" : "(在建)") + bm.getLine() + bm.getName() + "站 直线距离" + bm.getDistance() + "米";
            }
            basic.setSubway(sbs);
        }
        //单独查询本次开盘在售的装修情况
        String deco = this.detailMapper.getDecorateInfo(buildingId);
        basic.setDecorate(deco);
        //楼盘图片查询

        List<String> imgs = this.detailMapper.getImages(buildingId);
        basic.setImages(imgs);

        //查询楼盘动态并缓存获取开盘数据
        List<BuildingDynmicBean> bybs = this.detailMapper.getLastDynamicInfo(buildingId);
        if (bybs.size() > 0) {
            //处理多张图片
            BuildingDynmicBean bdb = new BuildingDynmicBean();
            bdb.setContent(bybs.get(0).getContent());
            bdb.setCreateTime(bybs.get(0).getCreateTime());
            bdb.setTitle(bybs.get(0).getTitle());
            bdb.setTotal(bybs.get(0).getTotal());
            List<String> dyImgs = new ArrayList<>();
            for (int i = 0; i < bybs.size(); i++) {
                String img = bybs.get(i).getTempImg();
                if (!StringUtils.isEmpty(img)) {
                    dyImgs.add(img);
                }
            }
            bdb.setImgs(dyImgs);
            basic.setDynamic(bdb);
        }
        int comments = basic.getCommentNum();
        //缓存基本信息
        basic.setCommentNum(null);
        // 楼盘优惠信息
        basic.setYhTitle(detailMapper.getYhTitle(buildingId, this.getDate()));
        this.cacheService.setBuildingBasicCache(basic);
        //缓存访问次数,肯定是第一次,缓存访问量，以后每次都往上加
        this.cacheService.setBuildingVisitsCache(buildingId, basic.getVisits());
        //缓存评论量，有评论后更新
        this.cacheService.setBuildingCommentCount(buildingId, comments);
        //构建并返回数据
        int isfocus = this.detailMapper.getIsfocus(buildingId, CurrentUser.getCurrentUserId());
        int isCollect = this.detailMapper.getIsCollect("building", buildingId, CurrentUser.getCurrentUserId());
        return ResultUtil.ok(buildData(basic, isfocus, isCollect));
    }

    private String getDate() {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.DATE, -45);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String time = sdf.format(c.getTime());
        return time + " 00:00:00";
    }

    private Map<String, Object> buildData(BuildingBasicBean basic, int isFoucus, int isCollect) {
        //构造基础数据结构,前端直接遍历
        List<BasicInfoVo> kvs = new ArrayList<>();
        dealKv(basic, kvs);
        Map<String, Object> m = new HashMap<>();
        m.put("covers", basic.getImages());
        m.put("tel", basic.getSaleTel());
        m.put("detail", kvs);
        m.put("subway", basic.getSubway());
        m.put("name", basic.getName());
        m.put("addr", basic.getRegion() + "-" + basic.getAddress());
        m.put("loc", basic.getLng() + "," + basic.getLat());
        m.put("state", getSellState(basic.getSellStatus()));
        m.put("stateX", basic.getSellState());
        Integer rank = basic.getRank();
        if (rank == null || rank > 99)
            m.put("rank", "99+");
        else
            m.put("rank", rank);
        m.put("dvrid", basic.getBrandId());
        m.put("price", basic.getPrice() == null ? "价格待定" : basic.getPrice());
        //添加访问量
        addBuildingVisits(basic.getId());
        int visits = this.cacheService.getCachedBuildingVisits(basic.getId());
        //除以10000保留一位小数
        DecimalFormat def = new DecimalFormat(".#");
        float vf = Float.valueOf(visits) / 10000f;
        m.put("visits", def.format(vf) + "w");
        m.put("deco", getDeco(basic.getDecorate()));
        m.put("dynamic", basic.getDynamic());
        m.put("isFocus", isFoucus > 0);
        m.put("isCollect", isCollect > 0);
        m.put("comments", this.cacheService.getBuildingCommentCount(basic.getId()) + 1);
        m.put("dpLink", basic.getDianPingLink());
        if (basic.getOverwrite() == null || basic.getOverwrite() == 1)//原来的数据是空，默认显示装修
            m.put("showDeco", true);
        else
            m.put("showDeco", false);
        m.put("yhTitle", basic.getYhTitle());
        return m;
    }


    private String getSellState(Integer s) {
        if (s == null)
            return "待售";
        SellStateEnum ss = SellStateEnum.getStateById(s);
        if (ss == null)
            return "待售";
        else
            return ss.getName();
    }

    private String getDeco(String deco) {
        if (deco == null)
            return "";
        if (deco.equals("rinsing"))
            return "清水";
        if (deco.equals("hardcover"))
            return "精装";
        return "精装/清水";
    }


    private void dealKv(BuildingBasicBean b, List<BasicInfoVo> kvs) {
        if (!StringUtils.isEmpty(b.getAlias()))
            kvs.add(new BasicInfoVo(0, "楼盘别名", b.getAlias(), null));
        if (!StringUtils.isEmpty(b.getPropType()))
            kvs.add(new BasicInfoVo(0, "物业类型", getPropType(b.getPropType()), null));
        if (!StringUtils.isEmpty(b.getLandPrice()))
            kvs.add(new BasicInfoVo(0, "项目地价", b.getLandPrice(), null));
        if (!StringUtils.isEmpty(b.getBrandName()))
            kvs.add(new BasicInfoVo(1, "开发商", b.getBrandName(), null));
        if (!StringUtils.isEmpty(b.getHeadOffice()))
            kvs.add(new BasicInfoVo(1, "企业品牌", b.getHeadOffice(), null));
        if (!StringUtils.isEmpty(b.getLoopLine()))
            kvs.add(new BasicInfoVo(0, "环线区间", b.getLoopLine(), null));
        if (!StringUtils.isEmpty(b.getRegion()) && !StringUtils.isEmpty(b.getStreet()))
            kvs.add(new BasicInfoVo(0, "区域板块", b.getRegion() + "-" + b.getStreet(), null));
        if (!StringUtils.isEmpty(b.getSpace()))
            kvs.add(new BasicInfoVo(0, "占地面积", b.getSpace(), null));
        if (!StringUtils.isEmpty(b.getBuiltSpace()))
            kvs.add(new BasicInfoVo(0, "规划面积", b.getBuiltSpace(), null));
        if (!StringUtils.isEmpty(b.getHouseModelRange()))
            kvs.add(new BasicInfoVo(0, "户型区间", b.getHouseModelRange(), null));
        if (!StringUtils.isEmpty(b.getVolumeRate()))
            kvs.add(new BasicInfoVo(0, "容积率", b.getVolumeRate(), null));
        if (!StringUtils.isEmpty(b.getGreenRate()))
            kvs.add(new BasicInfoVo(0, "绿化率", b.getGreenRate(), null));
        if (!StringUtils.isEmpty(b.getLvdilv()))
            kvs.add(new BasicInfoVo(0, "绿地率", b.getLvdilv(), null));
        if (!StringUtils.isEmpty(b.getHouseCounts()))
            kvs.add(new BasicInfoVo(0, "总户数", b.getHouseCounts(), null));
        if (!StringUtils.isEmpty(b.getBuildingNum()))
            kvs.add(new BasicInfoVo(0, "楼栋数", b.getBuildingNum(), null));
        if (!StringUtils.isEmpty(b.getFloorNum()))
            kvs.add(new BasicInfoVo(0, "楼层数", b.getFloorNum(), null));
        if (!StringUtils.isEmpty(b.getElevatorRate()))
            kvs.add(new BasicInfoVo(0, "梯户比", b.getElevatorRate(), null));
        if (!StringUtils.isEmpty(b.getCarport()))
            kvs.add(new BasicInfoVo(0, "车位数", b.getCarport(), null));
        if (!StringUtils.isEmpty(b.getPropCompanyName()))
            kvs.add(new BasicInfoVo(0, "物业公司", b.getPropCompanyName(), null));
        if (!StringUtils.isEmpty(b.getPropCost()))
            kvs.add(new BasicInfoVo(0, "物业费", b.getPropCost(), null));
        if (!StringUtils.isEmpty(b.getCompleteTime()))
            kvs.add(new BasicInfoVo(0, "交房时间", b.getCompleteTime(), null));
        if (!StringUtils.isEmpty(b.getSaleAddr()))
            kvs.add(new BasicInfoVo(2, "售楼地址", b.getSaleAddr(), b.getSaleAddrLocation()));//坐标当作参数传进去
    }

    //物业类型多选的，使逗号分隔开的。
    private String getPropType(String propType) {
        if (StringUtils.isEmpty(propType))
            return "";
        String[] ts = propType.split(",");
        String temp = "";
        for (String t : ts) {
            PropertyType pt = PropertyType.getPropTypeByName(t);
            if (pt == null)
                continue;
            temp += pt.getType() + "、";
        }
        if (temp.length() > 0)
            temp = temp.substring(0, temp.length() - 1);
        return temp;
    }


    /**
     * 查询并缓存开盘相关所有信息
     */
    @Override
    public Object getKaiPanInfo(Integer buildingId) {

        if (buildingId == null) {
            return ResultUtil.fail("楼盘ID不能为空");
        }
        List<OpenInfoBean> kps = this.cacheService.getBuildingOpenInfo(buildingId);
        if (kps != null) {
            //构建数据返回前端
            return buildKaiPanData(kps);
        }
        //判断是不是本来就没有开盘信息而不是没有缓存
        Integer x = this.cacheService.getBuildingNoOpenInfo(buildingId);
        if (x != null) {
            return ResultUtil.fail("楼盘无开盘信息");
        }
        //查询全部开盘信息
        kps = this.detailMapper.getAllOpenInfo(buildingId);
        if (kps.size() == 0) {
            //使用缓存标识无开盘信息
            this.cacheService.setBuildingNoOpenInfo(buildingId);
            return ResultUtil.fail("楼盘无开盘信息");
        }
        //查询开盘相关文档资料并标注是否有该资料
        List<OpenDocumetBean> odbs = this.detailMapper.getAllDocuMents(kps);
        formatOpenInfoAndDocuments(kps, odbs);
        //查询开盘房源剩余套数并附上中签率
        List<OpenHouseSuplus> suplus = this.detailMapper.getOpenHouseSuplus(kps);
        formatSuplusHouseAndOpenInfo(kps, suplus);
        //缓存除用户自己的数据以外的数据
        this.cacheService.setBuildingOpenInfo(buildingId, kps);

        //构建数据并返回前端
        return buildKaiPanData(kps);
    }

    //构建开盘数据返回给前端
    private Object buildKaiPanData(List<OpenInfoBean> kps) {

        Map<String, Object> m = new HashMap<>();
        //将预估总价除以10000
        formatTotalPrice(kps);
        //查询每次开盘是否存在摇号结果和复核结果
        List<VerifyYaoHaoVo> res = this.detailMapper.getHasYaoHaoResult(kps);
        formatYaoHaoRes(kps, res);
        //计算每次开盘的中签率
        calculateRate(kps);
        //处理开盘各阶段显示问题
        try {
            resolveKaipanStage(kps);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //查找当前开盘的信息
        List<OpenInfoBean> nowKaiPan = null;
        try {
            nowKaiPan = getKaiPanNow(kps);
            //查询当前开盘用户绑定摇号结果的记录
            //查询用户的摇号结果绑定数据
            if (nowKaiPan != null && nowKaiPan.size() > 0) {
                List<YaoHaoResultBindBean> binds = this.detailMapper
                        .getUserAllBinds(nowKaiPan, CurrentUser.getCurrentUserId());
                formatYaoHaoBinds(nowKaiPan, binds);
            }
            //按照售卖时间进行排序
            if (!CollectionUtils.isEmpty(nowKaiPan)) {
                nowKaiPan.sort(Comparator.comparing(OpenInfoBean::getPresellTime).reversed());
            }
            m.put("nowKaiPai", nowKaiPan.size() > 0 ? nowKaiPan : null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //2020-1-2日新增开盘提示语
        formatTips(nowKaiPan, kps);

        builderTips(nowKaiPan);


        //历史开盘数据
        List<OpenInfoBean> historyKaiPan = getHistoryKaiPan(kps);

        builderTips(historyKaiPan);
        m.put("historyKaiPan", historyKaiPan.size() > 0 ? historyKaiPan : null);
        //从历史开盘中，获取摇号剩余的房源信息列表
        List<SurplusHouseBean> sups = getSurplusHouse(historyKaiPan);
        m.put("surplusHouse", sups.size() == 0 ? null : sups);
        if (sups.size() > 0) {
            int supTotal = 0;
            for (SurplusHouseBean sup : sups) {
                supTotal = supTotal += sup.getSurplus();
            }
            m.put("surplusHouseTotal", supTotal);
        }
        return ResultUtil.ok(m);
    }

    private void builderTips(List<OpenInfoBean> infoBeans) {
        if (Objects.nonNull(infoBeans)) {
            String strNow = DaysIntUtil.dateFormat(new Date());
            long now = System.currentTimeMillis();
            infoBeans.forEach(info -> {
                BuildingBasicBean basicBean = detailMapper.getBaseInfo(info.getBuildingId());
                SellStateEnum sellStateEnum = SellStateEnum.getStateById(basicBean.getSellStatus());
//				SellStateEnum.getStateById(db.getSellStatus()).getName()
                boolean needTips = !SellStateEnum.WAIT_XINTUI.equals(sellStateEnum) && !SellStateEnum.SELL_OUT.equals(sellStateEnum);
                info.setStatePreseTime(-1);
                if (info.getPresellTime() != null) {
                    //解析取证日期
                    long prevSellTimeSt = DaysIntUtil.getDayStart(info.getPresellTime()).getTime();
                    long prevSellTImeEt = DaysIntUtil.getDayEnd(info.getPresellTime()).getTime();
                    if (prevSellTimeSt < now && prevSellTImeEt > now) {
                        if (needTips)
                            info.setTipsText("今日取证");
                        info.setStatePreseTime(0);
                    } else if (prevSellTimeSt > now) {
                        info.setStatePreseTime(-1);
                    } else {
                        info.setStatePreseTime(1);
                    }
                }

                //解析网上登记时间
                info.setStateRegistTime(-1);
                if (info.getRegisterStartTime() != null && info.getRegisterEndTime() != null) {
                    long registStart = DaysIntUtil.getDayStart(DaysIntUtil.setDayTime(info.getRegisterStartTime(), "09:00:00")).getTime();
                    long registEnd = DaysIntUtil.setDayTime(info.getRegisterEndTime(), "18:00:00").getTime();
                    if (now > registStart && now < registEnd) {
                        if (needTips) {
                            info.setTipsText("距离登记结束还有");
                            info.setTipsValue(registEnd - now);
                        }
                        info.setStateRegistTime(0);
                    } else if (now < registStart) {
                        info.setStateRegistTime(-1);
                    } else {
                        info.setStateRegistTime(1);
                        if (needTips) {
                            info.setTipsText("售楼部已开放,看房请提前预约");
                        }
                    }
                }

                //解析初核时间
                info.setStateVerifyTime(-1);
                if (info.getVerifyStartTime() != null && info.getVerifyEndTime() != null) {
                    long verifySt = DaysIntUtil.getDayStart(info.getVerifyStartTime()).getTime();
                    long verifyEt = DaysIntUtil.getDayEnd(info.getVerifyEndTime()).getTime();
                    if (now < verifySt) {
                        info.setStateVerifyTime(-1);
                    } else if (now > verifyEt) {
                        info.setStateVerifyTime(1);
                    } else {
                        info.setStateVerifyTime(0);
                    }
                }
                //解析看房时间
                info.setStateLookTime(-1);
                if (info.getLookStartTime() != null) {
                    long lookSt = DaysIntUtil.getDayStart(info.getLookStartTime()).getTime();
                    long lookEt;
                    if (info.getLookEndTime() != null) {
                        lookEt = DaysIntUtil.getDayEnd(info.getLookEndTime()).getTime();
                    } else {
                        lookEt = DaysIntUtil.getDayEnd(DaysIntUtil.dateNextDay(info.getLookStartTime(), 7)).getTime();
                    }
                    if (now < lookSt) {
                        info.setStateLookTime(-1);
                    } else if (now > lookEt) {
                        info.setStateLookTime(1);
                    } else {
                        info.setStateLookTime(0);
                    }
                }
                //解析复核时间
                info.setStateReverifyTime(-1);
                if (info.getReverifyStartTime() != null) {
                    long reverifySt = DaysIntUtil.getDayStart(info.getReverifyStartTime()).getTime();
                    long reverifyEt;
                    if (info.getReverifyEndTime() != null)
                        reverifyEt = DaysIntUtil.getDayEnd(info.getReverifyEndTime()).getTime();
                    else
                        reverifyEt = DaysIntUtil.getDayEnd(DaysIntUtil.dateNextDay(info.getReverifyStartTime(), 7)).getTime();
                    if (now < reverifySt) {
                        info.setStateReverifyTime(-1);
                    } else if (now > reverifyEt) {
                        info.setStateReverifyTime(1);
                    } else {
                        info.setStateReverifyTime(0);
                    }
                }
                boolean isPub = false;
                //解析名册公示时间
                info.setStatePublicityTime(-1);
                if (info.getPublicStartTime() != null) {
                    long publicitySt = DaysIntUtil.getDayStart(info.getPublicStartTime()).getTime();
                    long publicityEt;
                    if (info.getPublicEndTime() != null)
                        publicityEt = DaysIntUtil.getDayEnd(info.getPublicEndTime()).getTime();
                    else
                        publicityEt = DaysIntUtil.getDayEnd(info.getPublicStartTime()).getTime();
                    if (now < publicitySt) {
                        isPub = false;
                        info.setStatePublicityTime(-1);
                    } else if (now > publicityEt) {
                        isPub = true;
                        info.setStatePublicityTime(1);
                    } else {
                        isPub = true;
                        info.setStatePublicityTime(0);
                    }
                }
                //解析摇号时间
                info.setStateLotteryTime(-1);
                if (info.isNeedLottery()) {
                    if (info.getYaoHaoTime() != null) {
                        long lotterySt = DaysIntUtil.getDayStart(info.getYaoHaoTime()).getTime();
                        long lotteryEt = DaysIntUtil.getDayEnd(info.getYaoHaoTime()).getTime();
                        if (now < lotterySt) {
                            info.setStateLotteryTime(-1);
                        } else if (now > lotteryEt) {
                            info.setStateLotteryTime(1);
                        } else info.setStateLotteryTime(0);
                    }
                } else {
                    info.setStateLotteryTime(isPub ? 1 : -1);
                }
                //解析选房时间
                info.setStateChooseTime(-1);
                if (info.getChooseStartTime() != null) {
                    long chooseSt = DaysIntUtil.getDayStart(info.getChooseStartTime()).getTime();
                    long chooseEt;
                    if (info.getChooseEndTime() != null)
                        chooseEt = DaysIntUtil.getDayEnd(info.getChooseEndTime()).getTime();
                    else
                        chooseEt = DaysIntUtil.getDayEnd(DaysIntUtil.dateNextDay(info.getChooseStartTime(), 7)).getTime();
                    if (now < chooseSt) {
                        info.setStateChooseTime(-1);
                    } else if (now > chooseEt) {
                        info.setStateChooseTime(1);
                    } else {
                        info.setStateChooseTime(0);
                    }
                }

            });
        }
    }


    private void formatTips(List<OpenInfoBean> nowKaiPan, List<OpenInfoBean> all) {
        for (OpenInfoBean o : all) {
            if (isNow(o, nowKaiPan))
                continue;
            o.setTips(null);
        }
    }

    private boolean isNow(OpenInfoBean o, List<OpenInfoBean> nowKaiPan) {
        if (nowKaiPan == null)
            return false;
        for (OpenInfoBean n : nowKaiPan) {
            if (n.getId().intValue() == o.getId().intValue())
                return true;
        }
        return false;
    }

    private void formatTotalPrice(List<OpenInfoBean> kps) {
        kps.forEach(k -> {
            if (k.getMaxTotalPrice() == null) {
                k.setMaxTotalPrice(0);
            }
            if (k.getMinTotalPrice() == null) {
                k.setMinTotalPrice(0);
                return;
            }
            k.setMinTotalPrice(k.getMinTotalPrice() / 10000);
            k.setMaxTotalPrice(k.getMaxTotalPrice() / 10000);
        });
    }

    //将当前的开盘的摇号绑定查询记录绑定到开盘信息下
    private void formatYaoHaoBinds(List<OpenInfoBean> nowKaiPan, List<YaoHaoResultBindBean> binds) {
        if (binds == null || binds.size() == 0)
            return;
        if (nowKaiPan.size() == 1) {
            nowKaiPan.get(0).setBinds(binds);
            return;
        }
        for (OpenInfoBean k : nowKaiPan) {
            List<YaoHaoResultBindBean> bs = new ArrayList<>();
            for (YaoHaoResultBindBean yhb : binds) {
                if (yhb.getOrderNum().equals(k.getOrderNum()))
                    bs.add(yhb);
            }
            k.setBinds(bs);
        }
    }

    //格式化摇号结果到开盘信息里
    private void formatYaoHaoRes(List<OpenInfoBean> kps, List<VerifyYaoHaoVo> res) {

        if (res == null || res.size() == 0)
            return;

        for (OpenInfoBean o : kps) {
            for (VerifyYaoHaoVo s : res) {
                if (o.getOrderNum().equals(s.getOrderNum())) {
                    if (s.getType().equals("yh"))
                        o.setYaohaoRes(true);
                    if (s.getType().equals("fh"))
                        o.setFuheRes(true);
                }
            }
        }
    }

    private void resolveKaipanStage(List<OpenInfoBean> kps) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
        long now = sdf.parse(sdf.format(new Date())).getTime();

        for (OpenInfoBean k : kps) {
            //处理非空
            if (k.getPresellTime() != null) {
                long preSale = sdf.parse(sdf.format(k.getPresellTime())).getTime();
                if (now >= preSale)
                    k.setHasPresale(true);
            }
            if (k.getRegisterStartTime() != null) {
                long regst = sdf.parse(sdf.format(k.getRegisterStartTime())).getTime();
                if (regst <= now)
                    k.setHasRegister(true);
            }
            if (k.getVerifyStartTime() != null) {
                long vryst = sdf.parse(sdf.format(k.getVerifyStartTime())).getTime();
                if (vryst <= now)
                    k.setHasVerify(true);
            }
            if (k.getPublicStartTime() != null) {
                long pubst = sdf.parse(sdf.format(k.getPublicStartTime())).getTime();
                if (pubst <= now)
                    k.setHasPublify(true);
            }
            if (k.getYaoHaoTime() != null) {
                long yh = sdf.parse(sdf.format(k.getYaoHaoTime())).getTime();
                if (yh <= now)
                    k.setHasYaohao(true);
            }
            if (k.getChooseStartTime() != null) {
                long chst = sdf.parse(sdf.format(k.getChooseStartTime())).getTime();
                if (chst <= now)
                    k.setHasChooseHouseSt(true);
            }
            if (k.getChooseEndTime() != null) {
                long ched = sdf.parse(sdf.format(k.getChooseEndTime())).getTime();
                if (ched <= now)
                    k.setHasChooseHouseEd(true);
            }
            if (k.getLookStartTime() != null) {
                long lst = sdf.parse(sdf.format(k.getLookStartTime())).getTime();
                if (lst <= now) k.setHasLookHouseSt(true);
            }
            if (k.getLookEndTime() != null) {
                long let = sdf.parse(sdf.format(k.getLookStartTime())).getTime();
                if (let <= now) k.setHasLookHouseEt(true);
            }
            if (k.getReverifyStartTime() != null) {
                long rst = sdf.parse(sdf.format(k.getReverifyStartTime())).getTime();
                if (rst <= now) k.setHasReverifySt(true);
            }
            if (k.getReverifyEndTime() != null) {
                long ret = sdf.parse(sdf.format(k.getReverifyEndTime())).getTime();
                if (ret <= now) k.setHasReverifyEt(true);
            }
        }

        //处理文档资料
        for (OpenInfoBean k : kps) {
            List<OpenDocumetBean> docs = k.getDocs();
            if (docs == null || docs.size() == 0)
                continue;
            for (OpenDocumetBean doc : docs) {
                if (doc.getType().equals("decorationPrice"))
                    k.setDecoPrice(doc);
                if (doc.getType().equals("housingPrice"))
                    k.setHousePrice(doc);
                if (doc.getType().equals("registerRule"))
                    k.setRegisterRule(doc);
            }
            k.setDocs(null);
        }

    }


    //计算中签率
    private void calculateRate(List<OpenInfoBean> kps) {
        DecimalFormat df = new DecimalFormat("#####.##");
        for (OpenInfoBean o : kps) {
            //处理价格
            if (o.getMinPrice() == null || o.getMinPrice() == 0)
                o.setShowPrice("暂无");
            else
                o.setShowPrice(o.getMinPrice() / 100 + "-" + o.getMaxPrice() / 100 + "元/㎡");
            //处理装修
            if (o.getDecorate() != null && o.getDecorate().length() > 0) {
                if (o.getDecorate().equals("rinsing"))
                    o.setDecorate("清水");
                else if (o.getDecorate().equals("hardcover"))
                    o.setDecorate("精装");
                else
                    o.setDecorate("精装/清水");
            } else
                o.setDecorate("无装修信息");
            //处理房源总套数，如果不为空，则表示后面都显示-- 2019-12-5日新增
            if (o.getTotalHouseNum() != null) {
                o.setAllHouseNum(o.getTotalHouseNum());
                o.setPgHoseNum(null);
                o.setPtHouseNum(null);
                o.setGxHouseNum(null);
                o.setShowTable(false);//不显示中签率一栏
                continue;
            }
            //棚改
            int pgHose = o.getPgHoseNum() == null ? 0 : o.getPgHoseNum();
            int pgYhNum = o.getPgyhNum() == null ? 0 : o.getPgyhNum();
            if (o.getPgHoseNum() == null || o.getPgHoseNum() == 0)
                o.setPgRate("-");
            else if (o.getPgyhNum() == null || o.getPgyhNum() == 0)
                o.setPgRate("-");
            else {
                float r = Float.valueOf(o.getPgHoseNum()) / Float.valueOf(o.getPgyhNum());
                o.setPgRate(df.format(r * 100f) + "%");
            }
            //刚需
            int gxHouse = o.getGxHouseNum() == null ? 0 : o.getGxHouseNum();
            int gxYhNum = o.getGxyhNum() == null ? 0 : o.getGxyhNum();
            if (o.getGxHouseNum() == null || o.getGxHouseNum() == 0)
                o.setGxRate("-");
            else if (o.getGxyhNum() == null || o.getGxyhNum() == 0)
                o.setGxRate("-");
            else {
                float r = Float.valueOf(o.getGxHouseNum()) / Float.valueOf(o.getGxyhNum());
                o.setGxRate(df.format(r * 100f) + "%");
            }
            //普通  普通房源+（棚改房源-棚改报名人数）+（刚需房源-刚需报名人数）/ 普通报名人数+（刚需报名人数-刚需套数）+（棚改报名人数-棚改套数）
            int ptall = 0;
            int ptPeopleAll = 0;
            if (pgHose > pgYhNum)
                ptall += pgHose - pgYhNum;
            int x = pgYhNum - pgHose;
            if (x > 0) ptPeopleAll += x;
            if (gxHouse > gxYhNum)
                ptall += gxHouse - gxYhNum;
            int y = gxYhNum - gxHouse;
            if (y > 0) ptPeopleAll += y;
            if (o.getPtHouseNum() != null)
                ptall += o.getPtHouseNum();
            if (o.getPtHouseNum() == null || o.getPtHouseNum() == 0)
                o.setPtRate("-");
            else if (o.getPtyhNum() == null || o.getPtyhNum() == 0)
                o.setPtRate("-");
            else {
                float r = Float.valueOf(ptall) / Float.valueOf(o.getPtyhNum() + ptPeopleAll);
                o.setPtRate(df.format(r * 100f) + "%");
            }
            //全部
            int allHouse = pgHose + gxHouse + (o.getPtHouseNum() == null ? 0 : o.getPtHouseNum());
            int yhNum = pgYhNum + gxYhNum + (o.getPtyhNum() == null ? 0 : o.getPtyhNum());
            o.setAllyhNum(yhNum);
            o.setAllHouseNum(allHouse);
            if (yhNum > 0 && allHouse > 0) {
                float r = Float.valueOf(allHouse) / Float.valueOf(yhNum);
                o.setAllRate(df.format(r * 100f) + "%");
            } else {
                o.setAllRate("-");
            }
            if (yhNum == 0)
                o.setShowTable(false);

        }

    }


    //获取历史开盘的剩余房源数据
    private List<SurplusHouseBean> getSurplusHouse(List<OpenInfoBean> historyKaiPan) {
        List<SurplusHouseBean> sups = new ArrayList<>();
        for (OpenInfoBean o : historyKaiPan) {
            if (o.getSuplusHouse() == null)
                continue;
            if (o.getSuplusHouse() > 0) {
                SurplusHouseBean s = new SurplusHouseBean();
                s.setOrderNum(o.getOrderNum());
                s.setPrice(o.getMinPrice() / 100 + "-" + o.getMaxPrice() / 100 + "元/㎡");
                s.setProjectName(o.getProjectName());
                s.setSurplus(o.getSuplusHouse());
                sups.add(s);
            }
        }
        return sups;
    }


    //过滤出历史开盘信息，排出当前开盘和未开盘的信息
    private List<OpenInfoBean> getHistoryKaiPan(List<OpenInfoBean> kps) {
        List<OpenInfoBean> history = new ArrayList<OpenInfoBean>();
        //历史开盘,当前时间>选房结束+5天
        long nt = System.currentTimeMillis();
        for (OpenInfoBean o : kps) {
            if (o.getPresellTime() == null){
                break;
            }
            long endChooseTime;
            if (o.getChooseStartTime() != null) {
                if (o.getChooseEndTime() == null)
                    endChooseTime = DaysIntUtil.dateNextDay(o.getChooseStartTime(), 7).getTime();
                else endChooseTime = o.getChooseEndTime().getTime();
                if (nt > endChooseTime)
                    history.add(o);
            }
            else if (o.getYaoHaoTime() != null){
                Date yaohaoEnd = DaysIntUtil.setDayTime(DaysIntUtil.dateNextDay(o.getYaoHaoTime(), 7), "23:59:59");
                if (nt > yaohaoEnd.getTime()){
                    history.add(o);
                }
            }else if (o.getRegisterEndTime() != null){
                Date registEnd = DaysIntUtil.setDayTime(DaysIntUtil.dateNextDay(o.getRegisterEndTime(), 4), "23:59:59");
                if (nt > registEnd.getTime()){
                    history.add(o);
                }
            }else{
                if (nt > (o.getPresellTime().getTime() + 7 * 24 * 60 * 60 * 1000L)) {
                    history.add(o);
                }
            }

        }
        return history;
    }


    //过滤出正在开盘的开盘信息
    private List<OpenInfoBean> getKaiPanNow(List<OpenInfoBean> kps) throws Exception {
        List<OpenInfoBean> now = new ArrayList<>();
        //当前开盘的信息  预售时间<当前<选房结束+4天
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
        long n = sdf.parse(sdf.format(new Date())).getTime();
        for (OpenInfoBean o : kps) {
            if (o.getPresellTime() == null) {
                continue;
            }
            long preSaleTime = sdf.parse(sdf.format(o.getPresellTime())).getTime();
            if (o.getChooseStartTime() != null){
                Date dtEnd;
                if (o.getChooseEndTime() == null){
                    dtEnd = DaysIntUtil.dateNextDay(o.getChooseStartTime(), 7);
                }else {
                    dtEnd = o.getChooseEndTime();
                }
                long endChooseTime = sdf.parse(sdf.format(dtEnd)).getTime();
                if (/*o.getChooseStartTime().getTime() <= n &&*/ n <= endChooseTime) {
                    now.add(o);
                }
            }
            /*if (o.getChooseEndTime() != null) {
                long endChooseTime = sdf.parse(sdf.format(o.getChooseEndTime())).getTime() + (4 * 24 * 60 * 60 * 1000L);
                if (preSaleTime <= n && n <= endChooseTime) {
                    now.add(o);
                }
            }*/ else if (o.getRegisterStartTime() == null) {//如果没有登记时间  +7天
                if (n <= (preSaleTime + 7 * 24 * 60 * 60 * 1000L)) {
                    now.add(o);
                }
            } else if (o.getYaoHaoTime() == null) {//如果没有摇号时间 +12天
                if (n <= (preSaleTime + 12 * 24 * 60 * 60 * 1000L)) {
                    now.add(o);
                }
            } else if (o.getChooseEndTime() == null) {    //如果没有选房结束时间 +15天
                if (n <= (preSaleTime + 15 * 24 * 60 * 60 * 1000L)) {
                    now.add(o);
                }
            }
        }
        return now;
    }


    //预售证号是正确的则剩余房源查询为正常
    private void formatSuplusHouseAndOpenInfo(List<OpenInfoBean> kps, List<OpenHouseSuplus> suplus) {
        if (suplus.size() == 0)
            return;
        List<OpenInfoBean> nowKaiPan = null;
        try {
            nowKaiPan = getKaiPanNow(kps);
        } catch (Exception e) {
        }
        int suplusTotal = 0;
        for (OpenHouseSuplus oh : suplus) {
            boolean isEq = false;
            for (OpenInfoBean o : nowKaiPan) {
                //排除本次开盘的预售证号的剩余房源
                if (o.getOrderNum().equals(oh.getOrderNum())) {
                    isEq = true;
                    break;
                }
            }
            if (!isEq)
                suplusTotal += oh.getSuplus();
        }
        if (suplusTotal < 20)
            return;
        //所有的开盘信息的剩余房源超过20套才展示
        for (OpenInfoBean kp : kps) {
            if (kp.getBuildingId().intValue() == 10002769)//中海云麓世家不显示
                continue;
            if (kp.getBuildingId().intValue() == 10002613) //金科集美学府不显示剩余房源
                continue;
            if (kp.getBuildingId().intValue() == 10002751)//建发中央湾区不显示
                continue;
            for (OpenHouseSuplus oh : suplus) {
                if (kp.getOrderNum().equals(oh.getOrderNum())) {
                    kp.setSuplusHouse(oh.getSuplus());
                    break;
                }
            }
        }
    }


    //将开盘的文档资料绑定到具体的开盘信息下面备用
    private void formatOpenInfoAndDocuments(List<OpenInfoBean> kps, List<OpenDocumetBean> odbs) {
        for (OpenInfoBean kp : kps) {
            if (kp.getDocs() == null)
                kp.setDocs(new ArrayList<>());
            for (OpenDocumetBean wd : odbs) {
                if (wd.getOpenId().intValue() == kp.getId())
                    kp.getDocs().add(wd);
            }
        }
    }


    /**
     * 查询楼盘前几条评论及回复默认评论， 置业顾问和剩余两个固定栏目数据。该缓存的缓存
     */
    @Override
    public Object getCommentsAndOthersInfoV2_1(Integer buildingId) {
        if (buildingId == null)
            return ResultUtil.fail("楼盘ID为空");
        //查询评论及点赞信息
        List<BuildingCommentBean> cms = this.detailMapper
                .getBuildingDetailComments(buildingId, CurrentUser.getCurrentUserId());
        //查询，默认的加群评论
        BuildingCommentBean defComent = this.detailMapper
                .getDefaultComment(buildingId, CurrentUser.getCurrentUserId());
        List<BuildingCommentBean> res = new ArrayList<>();
        res.add(defComent);
        res.addAll(cms);
        //处理如果是置业顾问的评论
        res.forEach(r -> {
            if (r == null)
                return;
            if (!StringUtils.isEmpty(r.getCname()))
                r.setCustomerName(r.getCname());
        });
        //查询这三条评论的所有回复以及回复的回复
        if (res.size() > 0) {
            List<BuildingCommentReply> replys = this.detailMapper.getCommentReply(res);
            if (replys.size() > 0)
                formatCommentAndReplys(res, replys);
        }

        //查询竞品，两条
        List<BuildingCompetitor> bcs = this.cacheService.getBuildingCompetitors(buildingId);
        if (bcs == null) {
            bcs = this.detailMapper.getCompetitor(buildingId);
            this.cacheService.setBuildingDetailCompetitor(buildingId, bcs);
        }
        //格式化竞品销售状态
        for (BuildingCompetitor bc : bcs) {
            String ss = this.getSellState(bc.getSellStatus());
            bc.setSaleState(ss);
        }
        //查询资讯
        List<BuildingInformationBean> imf = this.cacheService.getBuildingDetaiInformation(buildingId);
        if (imf == null) {
            imf = this.detailMapper.getBuildingInformation(buildingId);
            this.cacheService.setBuildingDetailInfomation(buildingId, imf);
        }

        //查询优秀置业顾问
        List<SaleManBean> smb = this.cacheService.getBuildingDetailSaleManV2_1(buildingId);
        if (smb == null || smb.size() == 0) {
            //先按照活跃度查询
            smb = this.detailMapper.getSaleManV2_1(buildingId, DaysIntUtil.getDays(new Date()) - 30);//按照活跃度排
            if (smb.size() == 0)
                this.cacheService.setBuildingDetailSaleManV2_1(buildingId, new ArrayList<>());
            else
                this.cacheService.setBuildingDetailSaleManV2_1(buildingId, smb);
        }
        Map<String, Object> m = new HashMap<>();
        m.put("comment", res);
        m.put("otherBuilding", bcs.size() == 0 ? null : bcs);
        m.put("information", imf.size() == 0 ? null : imf);
        m.put("saleMan", smb.size() == 0 ? null : smb);
        return ResultUtil.ok(m);
    }

    /**
     * 查询楼盘前几条评论及回复默认评论， 置业顾问和剩余两个固定栏目数据。该缓存的缓存
     */
    @Override
    public Object getCommentsAndOthersInfoV2_2(Integer buildingId) {
        if (buildingId == null)
            return ResultUtil.fail("楼盘ID为空");
        //查询评论及点赞信息
        List<BuildingCommentBean> cms = this.detailMapper
                .getBuildingDetailComments(buildingId, CurrentUser.getCurrentUserId());
        //查询，默认的加群评论
        BuildingCommentBean defComent = this.detailMapper
                .getDefaultComment(buildingId, CurrentUser.getCurrentUserId());
        List<BuildingCommentBean> res = new ArrayList<>();
        res.add(defComent);
        res.addAll(cms);
        //处理如果是置业顾问的评论
        res.forEach(r -> {
            if (r == null)
                return;
            if (!StringUtils.isEmpty(r.getCname()))
                r.setCustomerName(r.getCname());
        });
        //查询这三条评论的所有回复以及回复的回复
        if (res.size() > 0) {
            List<BuildingCommentReply> replys = this.detailMapper.getCommentReply(res);
            if (replys.size() > 0)
                formatCommentAndReplys(res, replys);
        }

        //查询竞品，两条
        List<BuildingCompetitor> bcs = this.cacheService.getBuildingCompetitors(buildingId);
        if (bcs == null) {
            bcs = this.detailMapper.getCompetitor(buildingId);
            this.cacheService.setBuildingDetailCompetitor(buildingId, bcs);
        }
        //格式化竞品销售状态
        for (BuildingCompetitor bc : bcs) {
            String ss = this.getSellState(bc.getSellStatus());
            bc.setSaleState(ss);
        }

		/*//查询资讯
		List<BuildingInformationBean> imf  = this.cacheService.getBuildingDetaiInformation(buildingId);
		if(imf==null) {
			imf = this.detailMapper.getBuildingInformation(buildingId);
			this.cacheService.setBuildingDetailInfomation(buildingId, imf);
		}*/

        // 查询资讯
        List<BuildingInformationBean> imfV2_2 = this.cacheService.getBuildingDetaiInformationV2_2(buildingId);
        if (imfV2_2 == null) {
            imfV2_2 = this.detailMapper.getBuildingInformationV2_2(buildingId, 5);
            this.dealTime(imfV2_2);
            this.cacheService.setBuildingDetaiInformationV2_2(buildingId, imfV2_2);
        }
        // 查询楼盘文章
        List<BuildingInformationBean> articles = this.cacheService.getBuildingArticles(buildingId);
        if (articles == null) {
            articles = this.detailMapper.getBuildingInformationV2_2(buildingId, null);
            this.dealTime(articles);
            this.cacheService.setBuildingArticles(buildingId, articles);
        }

        //---------------------------
        //查询优秀置业顾问
        List<SaleManBean> smb = this.cacheService.getBuildingDetailSaleManV2_1(buildingId);
        if (CollectionUtils.isEmpty(smb)) {
            //先按照活跃度查询 按照活跃度排
            smb = this.detailMapper.getSaleManV2_1(buildingId, DaysIntUtil.getDays(new Date()) - 30);
            //查询昨日之星第一个
            SaleManBean y = homePageService.getYesterdayStar(buildingId);

            //查询是否有竞价上首页的
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            //查询当前竞价最高
            SaleManBean s = hpm.getHomePageSaleManChuJia(sdf.format(new Date()), buildingId, BidTypeEnum.BUILD_PAGE_BID.getType());

            addIndexSaleMan(smb, 1, y);
            addIndexSaleMan(smb, 2, s);

            this.cacheService.setBuildingDetailSaleManV2_1(buildingId, smb);
        }
        Map<String, Object> m = new HashMap<>(6);
        m.put("comment", res);
        m.put("otherBuilding", bcs.size() == 0 ? null : bcs);
        m.put("information", imfV2_2.size() == 0 ? null : imfV2_2);
        m.put("articles", articles.size() == 0 ? null : articles);
        m.put("saleMan", smb.size() == 0 ? null : smb);
        return ResultUtil.ok(m);
    }

    private boolean isNotEq(List<SaleManBean> golden, int customerId) {
        return CollectionUtils.isEmpty(golden.stream().filter(saleManBean -> saleManBean.getCid() == customerId).collect(Collectors.toList()));
    }

    private void addIndexSaleMan(List<SaleManBean> golden,int index, SaleManBean saleManBean){
        if(ObjectUtils.isEmpty(saleManBean) || !isNotEq(golden, saleManBean.getCid())){
            return;
        }
        if (!ObjectUtils.isEmpty(golden) && golden.size() >= index){
            golden.set(index, saleManBean);
        }else {
            golden.add(saleManBean);
        }
    }

    // 处理展示时间
    private void dealTime(List<BuildingInformationBean> imfV2_2) {
        if (imfV2_2 == null || imfV2_2.size() < 1)
            return;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        imfV2_2.forEach(i -> {
            i.setShowTime(sdf.format(i.getCreateTime()));
            i.setCreateTime(null);
        });
    }

    //格式化楼盘评论的回复内容
    private void formatCommentAndReplys(List<BuildingCommentBean> res, List<BuildingCommentReply> replys) {

        //1、将回复的回复放在各自下面处理,并提取第一级别的回复，不然会重复处理
        List<BuildingCommentReply> firsetLevel = new ArrayList<>();
        for (BuildingCommentReply br : replys) {
            if (br.getReplyId() == 0)
                firsetLevel.add(br);
            //如果置业顾问的名字不为空，则将顾客的名字改为置业问得名字
            if (!StringUtils.isEmpty(br.getCname()))
                br.setCustomerName(br.getCname());
            for (BuildingCommentReply b : replys) {
                if (b.getReplyId().intValue() == br.getId()) {
                    if (br.getReply() == null)
                        br.setReply(new ArrayList<>());
                    br.getReply().add(b);
                }
            }
        }

        //2、将所有的一级回复分开在各自的评论下,子集一级关联了
        for (BuildingCommentBean bc : res) {
            for (BuildingCommentReply br : firsetLevel) {
                if (br.getCommentId().intValue() == bc.getId()) {
                    if (bc.getReply() == null)
                        bc.setReply(new ArrayList<>());
                    bc.getReply().add(br);
                }
            }
        }

        //3、递归处理回复消息
        for (BuildingCommentBean bc : res) {
            if (bc.getReply() != null) {
                List<BuildingCommentReplyVo> result = new ArrayList<>();
                dealReply(bc.getReply(), result, bc.getCustomerName());
                bc.setReplys(result);
                bc.setReply(null);
            }
        }
    }


    private void dealReply(List<BuildingCommentReply> reps, List<BuildingCommentReplyVo> res, String commentUserName) {
        for (BuildingCommentReply br : reps) {
            if (br.getReplyId().intValue() == 0) {
                BuildingCommentReplyVo bv = new BuildingCommentReplyVo();
                bv.setContent(br.getContent());
                if (br.getCustomerType().equals("consultant"))
                    bv.setReplyerName("置业顾问" + br.getCustomerName());
                else
                    bv.setReplyerName(br.getCustomerName());
                bv.setBeRelyedName(commentUserName);
                bv.setReplyUserId(br.getCustomerId());
                bv.setReplyUserType(br.getCustomerType());
                bv.setCommentId(br.getCommentId());
                bv.setId(br.getId());
                res.add(bv);
                if (br.getReply() != null)
                    dealReply(br.getReply(), res, br.getCustomerName());
            } else {
                BuildingCommentReplyVo bv = new BuildingCommentReplyVo();
                bv.setContent(br.getContent());
                if (br.getCustomerType().equals("consultant"))
                    bv.setReplyerName("置业顾问" + br.getCustomerName());
                else
                    bv.setReplyerName(br.getCustomerName());
                bv.setBeRelyedName(commentUserName);
                bv.setReplyUserId(br.getCustomerId());
                bv.setReplyUserType(br.getCustomerType());
                bv.setCommentId(br.getCommentId());
                bv.setId(br.getId());
                res.add(bv);
                if (br.getReply() != null)
                    dealReply(br.getReply(), res, br.getCustomerName());
            }
        }
    }


    /**
     * 楼盘分享的二维码图片，后期在做海报处理
     */
    @Override
    public Object getBuildingQRcode(Integer buildingId, String pageUrl) {

        if (StringUtils.isEmpty(pageUrl))
            return ResultUtil.fail("页面路径不能为空");
        if (buildingId == null)
            return ResultUtil.fail("楼盘ID不能为空");
        Map<String, String> m = new HashMap<>();
        m.put("page", pageUrl);
//    	Map<String,String> mx = new HashMap<>();
//    	mx.put("buildingId", buildingId+"");
        m.put("scene", buildingId + "");
        HttpHeaders headers = new HttpHeaders();
        //设置请求媒体数据类型
        headers.setContentType(MediaType.APPLICATION_JSON);
        String json = JSON.toJSONString(m);
        HttpEntity<String> formEntity = new HttpEntity<String>(json, headers);
        ResponseEntity<byte[]> res = restTemplate.postForEntity(QR_IMG_HOST + wxAcctkCacheService.getMiniprogramAcctk(),
                formEntity, byte[].class);
        byte[] x = res.getBody();
        Object img = new String(Base64.getEncoder().encode(x));
        return ResultUtil.ok(img);
    }

    @Override
    public Object getBuildingImgs(Integer buildingId, String type) {

        if (buildingId == null)
            return ResultUtil.fail("楼盘ID不能为空");
        if (StringUtils.isEmpty(type))
            return ResultUtil.fail("楼盘分类不能为空");
        List<BuildingImgBean> imgs = this.cacheService.getBuildingImages(buildingId);
        if (imgs == null) {
            imgs = this.detailMapper.getAllBuildingImg(buildingId);
            this.cacheService.setBuildingDetailImgs(buildingId, imgs);
        }
        if (imgs.size() > 0) {
            List<BuildingImgBean> timgs = new ArrayList<>();
            for (BuildingImgBean img : imgs) {
                if (img.getType().equals(type))
                    timgs.add(img);
            }
            return ResultUtil.ok(timgs);
        }
        return ResultUtil.fail("楼盘无图片");
    }


    /**
     * 获取楼盘户型
     */
    @Override
    public Object getHouseModel(Integer buildingId, String type) {

        if (buildingId == null)
            return ResultUtil.fail("楼盘id不能为空");
        if (StringUtils.isEmpty(type))
            return ResultUtil.fail("type不能为空");
        List<BuildingHouseModelBean> models = this.cacheService.getBuildingModel(buildingId);
        if (models == null) {
            models = this.detailMapper.getHouseModel(buildingId);
            //格式化面积数据
            models.forEach(m -> {
                String a = m.getHouseSpace();
                Integer x = m.getYuanLaiArea();
                if (x != null && StringUtils.isEmpty(a)) {
                    m.setHouseSpace(x + "m²");
                    return;
                }
            });
            this.cacheService.setBuildingHouseModel(buildingId, models);
        }

        if (models.size() > 0) {
            //计算每个户型的数量，不用去找数据库了
            Map<String, Integer> counts = new HashMap<>();
            for (BuildingHouseModelBean m : models) {
                if (type.equals("current") && m.getCurrent().intValue() != 1)
                    continue;
                if (counts.get(m.getType()) == null)
                    counts.put(m.getType(), 1);
                else
                    counts.put(m.getType(), counts.get(m.getType()) + 1);
            }
            Map<String, List<BuildingHouseModelBean>> types = new HashMap<>();
            for (BuildingHouseModelBean m : models) {
                if (type.equals("current") && m.getCurrent().intValue() != 1)
                    continue;
                List<BuildingHouseModelBean> temp = types.get(m.getType());
                if (temp == null)
                    types.put(m.getType(), temp = new ArrayList<>());
                temp.add(m);
            }
            List<BuildingHouseModelBean> all = new ArrayList<>();
            for (BuildingHouseModelBean m : models) {
                if (type.equals("current") && m.getCurrent().intValue() != 1)
                    continue;
                all.add(m);
            }
            Map<String, Object> res = new HashMap<>();
            res.put("counts", counts.size() == 0 ? null : counts);
            res.put("types", types.size() == 0 ? null : types);
            res.put("all", all.size() == 0 ? null : all);
            return ResultUtil.ok(res);
        }
        return ResultUtil.fail("暂无户型图数据");

    }

    /**
     * 获取楼盘户型,新增户型 测评部分
     */
    @Override
    public Object getHouseModelV2_2(Integer buildingId, String type) {

        if (buildingId == null)
            return ResultUtil.fail("楼盘id不能为空");
        if (StringUtils.isEmpty(type))
            return ResultUtil.fail("type不能为空");
        List<BuildingHouseModelBean> models = this.cacheService.getBuildingModelV2_2(buildingId);
        if (models == null) {
            models = this.detailMapper.getHouseModelV2_2(buildingId);
            //格式化面积数据
            models.forEach(m -> {
                String a = m.getHouseSpace();
                Integer x = m.getYuanLaiArea();
                if (x != null && StringUtils.isEmpty(a)) {
                    m.setHouseSpace(x + "m²");
                }
                //处理评测
                if (m.getReviewId() != null) {
                    Float s = Float.valueOf(m.getReviewScore());
                    m.setReviewScore_(s / 10f);
                    m.setReviewScore(null);
                    if (!StringUtils.isEmpty(m.getReviewLabel())) {
                        m.setReviewLabel_(m.getReviewLabel().split("、"));
                        m.setReviewLabel(null);
                    }
                }
            });
            this.cacheService.setBuildingHouseModelV2_2(buildingId, models);
        }

        if (models.size() > 0) {
            //计算每个户型的数量，不用去找数据库了
            Map<String, Integer> counts = new HashMap<>();
            for (BuildingHouseModelBean m : models) {
                if (type.equals("current") && m.getCurrent().intValue() != 1)
                    continue;
                if (counts.get(m.getType()) == null)
                    counts.put(m.getType(), 1);
                else
                    counts.put(m.getType(), counts.get(m.getType()) + 1);
            }
            Map<String, List<BuildingHouseModelBean>> types = new HashMap<>();
            for (BuildingHouseModelBean m : models) {
                if (type.equals("current") && m.getCurrent().intValue() != 1)
                    continue;
                List<BuildingHouseModelBean> temp = types.get(m.getType());
                if (temp == null)
                    types.put(m.getType(), temp = new ArrayList<>());
                temp.add(m);
            }
            List<BuildingHouseModelBean> all = new ArrayList<>();
            for (BuildingHouseModelBean m : models) {
                if (type.equals("current") && m.getCurrent().intValue() != 1)
                    continue;
                all.add(m);
            }
            Map<String, Object> res = new HashMap<>();
            res.put("counts", counts.size() == 0 ? null : counts);
            res.put("types", types.size() == 0 ? null : types);
            res.put("all", all.size() == 0 ? null : all);
            return ResultUtil.ok(res);
        }
        return ResultUtil.fail("暂无户型图数据");

    }


    @Override
    public Object getBuildingAndDecorate(String orderNum) {
        if (StringUtils.isEmpty(orderNum))
            return ResultUtil.fail("预售证号不能为空");
        List<BuildingDecoVo> decos = this.detailMapper.getDecoPaln(orderNum);
        List<BuildingNumAndDecoVo> nums = this.detailMapper.getBuildingNum(orderNum);
        if (decos.size() > 0 && nums.size() > 0) {//说明有装修，可能全是精装或精装/清水
            String x = decos.get(0).getRange();
            //如果装修范围是空，则说明全是精装
            if (StringUtils.isEmpty(x)) {
                nums.forEach(n -> n.setDeco(1));
            } else {
                String[] nx = x.split("\\+");
                for (String n : nx) {
                    for (BuildingNumAndDecoVo dv : nums) {
                        if (n.trim().equals(dv.getNum().trim()))
                            dv.setDeco(1);
                    }
                }
            }
        }
        Map<String, Object> m = new HashMap<>();
        m.put("decos", decos.size() > 0 ? decos : null);
        m.put("nums", nums.size() > 0 ? nums : null);
        return ResultUtil.ok(m);
    }


    //  * 房源价格 1
//  * 总价低到高  2
//  * 总价高到低 3
//  * 单价低到高 4
//  * 单价高到底5
//  * 面积从低到高6
//  * 面积从高到低 7
    @Override
    public Object searchHousePrice(String orderNum, Integer page, Integer orderBy, Integer canSale, String num) {

        if (StringUtils.isEmpty(orderNum))
            return ResultUtil.fail("预售证号不能为空");
        if (StringUtils.isEmpty(num))
            num = null;
        if (page == null)
            page = 1;
        if (orderBy == null)
            orderBy = 1;
        if (canSale == null)
            canSale = 0;
        Map<String, Object> m = new HashMap<>();
        m.put("orderNum", orderNum);
        m.put("page", (page - 1) * 10);
        m.put("orderBy", orderBy);
        m.put("canSale", canSale);
        m.put("num", num);
        List<HousePriceBean> hps = this.detailMapper.searchHousePrice(m);
        if (hps.size() > 0) {
            hps.forEach(hp -> {
                if (hp.getUnitNum().equals("其他"))
                    hp.setUnitNum("1单元");
            });
        }
        int total = this.detailMapper.searchHosePriceTotal(m);
        m.clear();
        m.put("rows", hps);
        m.put("total", total);
        return ResultUtil.ok(m);
    }

    @Override
    public Object getHistoryKaiPan(Integer buildingId) {
        if (buildingId == null)
            return ResultUtil.fail("楼盘id不能为空");
        ResultBean r = (ResultBean) getKaiPanInfo(buildingId);
        if (r.getCode() != 200)
            return r;
        @SuppressWarnings("unchecked")
        Map<String, Object> m = (Map<String, Object>) r.getData();
        @SuppressWarnings("unchecked")
        List<OpenInfoBean> historyKaiPan = (List<OpenInfoBean>) m.get("historyKaiPan");
        return ResultUtil.ok(historyKaiPan);
    }

    @Override
    public Object getAllComments(Integer buildingId, Integer page) {
        if (buildingId == null)
            return ResultUtil.fail("楼盘id不能为空");
        if (page == null)
            page = 1;
        List<BuildingCommentBean> coms = this.detailMapper
                .getCommentByPage(buildingId, (page - 1) * 10, CurrentUser.getCurrentUserId());
        coms.forEach(c -> {
            if (!StringUtils.isEmpty(c.getCname()))
                c.setCustomerName(c.getCname());
        });
        if (coms.size() > 0) {
            List<BuildingCommentReply> replys = this.detailMapper.getCommentReply(coms);
            if (replys.size() > 0)
                formatCommentAndReplys(coms, replys);
        }
        Map<String, Object> res = new HashMap<>();
        res.put("coms", coms.size() == 0 ? null : coms);
        res.put("total", coms.size() == 0 ? 0 : this.detailMapper.getCommentsTotal(buildingId));
        //第一页时候加入楼盘名字
        if (page == 1) {
            String name = this.detailMapper.getBuildingName(buildingId);
            res.put("name", name);
        }
        return ResultUtil.ok(res);
    }


    @Override
    public Object AddComments(BuildingCommentCommand comment) {
        if (comment.getBuildingId() == null)
            return ResultUtil.fail("评论失败");
        if (StringUtils.isEmpty(comment.getContent()))
            return ResultUtil.fail("评论失败");
        if (!commonService.checkContent(comment.getContent()))
            return ResultUtil.fail("评论内容含有敏感词汇");
        int cid = CurrentUser.getCurrentUserId();
        //调用用户服务获取置业顾问信息
        if (!canComment(cid, comment.getBuildingId()))
            return ResultUtil.fail("置业顾问只能在绑定的楼盘下评论");
        //直接添加评论
        BuildingCommentBean c = new BuildingCommentBean();
        c.setBuildingId(comment.getBuildingId());
        c.setContent(comment.getContent());
        c.setCreateTime(new Date());
        c.setCustomerId(cid);
        int x = this.detailMapper.addBuildingComment(c);
        if (x > 0) {
            this.cacheService.addComments(comment.getBuildingId());
            return ResultUtil.ok();
        }
        return ResultUtil.fail("评论失败");
    }

    /**
     * 该用户是否可以在该楼盘下评论
     */
    private boolean canComment(int cid, int buildingId) {
        String url = customerServiceUrl + "/getSellManInfo?sellManCustomerId=" + cid;
        String res = this.ribonTemplate.getForObject(url, String.class);
        log.info("服务内部调用置业顾问信息接口:" + res);
        JSONObject result = JSON.parseObject(res);
        int code = result.getIntValue("code");
        if (code != 200)
            return true;
        JSONObject data = result.getJSONObject("data");
        if (data == null)
            return true;
        Integer sellManBuildingId = data.getInteger("buildingId");
        if (sellManBuildingId == null)
            return true;
        if (sellManBuildingId.intValue() == buildingId)
            return true;
        return false;
    }

    /**
     * <p>回复楼盘的评论，如果是置业顾问则加分
     */
    public Object commentReply(BuildingCommentReplyCommand reply) {

        if (StringUtils.isEmpty(reply.getContent()))
            return ResultUtil.fail("回复的内容不能为空");
        if (reply.getBuildingId() == null)
            return ResultUtil.fail("回复失败");
        if (reply.getComId() == null)
            return ResultUtil.fail("回复失败");
        if (reply.getReplyId() == null)
            reply.setReplyId(0);
        //判断是否含有非法词汇
        if (!this.commonService.checkContent(reply.getContent()))
            return ResultUtil.fail("回复内容包含非法词汇");
        int customerId = CurrentUser.getCurrentUserId();
        //查询是否是置业顾问且不能回复其它楼盘
        int x = this.canReply(reply, customerId);
        if (x < 0)
            return ResultUtil.fail("置业顾问只能回复本楼盘下的评论哦");
        //执行回复
        BuildingCommentReply r = new BuildingCommentReply();
        r.setCommentId(reply.getComId());
        r.setContent(reply.getContent());
        r.setCreateTime(new Date());
        r.setCustomerId(customerId);
        r.setReplyId(reply.getReplyId());
        r.setBuildingId(reply.getBuildingId());
        int index = this.detailMapper.addCommentReply(r);
        if (index > 0) {
            //如果是置业顾问的话要加分
            if (x == 1) {
                //异步调用加分和消息提示
                this.commonService.runInThreadPool(() -> {
                    addScore(customerId, reply.getBuildingId());
                    commentReplyMsg(reply, true, customerId);
                });
            } else {
                this.commonService.runInThreadPool(() -> {
                    commentReplyMsg(reply, false, customerId);
                });
            }
            return ResultUtil.ok();
        }
        return ResultUtil.fail("回复失败");
    }


    private int canReply(BuildingCommentReplyCommand reply, int customerId) {
        String url = customerServiceUrl + "/getSellManInfo?sellManCustomerId=" + customerId;
        String res = this.ribonTemplate.getForObject(url, String.class);
        log.info("服务内部调用置业顾问信息接口:" + res);
        JSONObject result = JSON.parseObject(res);
        int code = result.getIntValue("code");
        if (code != 200)
            return 0;
        JSONObject data = result.getJSONObject("data");
        if (data == null)
            return 0;
        Integer sellManBuildingId = data.getInteger("buildingId");
        if (sellManBuildingId == null)
            return 0;
        if (sellManBuildingId.intValue() == reply.getBuildingId().intValue())
            return 1;
        return -1;
    }

    private void addScore(int sellManCustomerId, int buildingId) {
        String url = customerServiceUrl + "/addReplyScore?"
                + "sellManCustomerId=" + sellManCustomerId + "&buildingId=" + buildingId;
        String res = this.ribonTemplate.getForObject(url, String.class);
        log.info("服务内部调用置业顾问回复加分接口:" + res);
    }

    private void commentReplyMsg(BuildingCommentReplyCommand reply, boolean isSellMan, int currentUserId) {
        Integer toCustomerId = null;
        //查询推送的目标用户的id
        if (reply.getReplyId() != null && reply.getReplyId() != 0) {
            //回复的回复，从回复表里查
            toCustomerId = this.detailMapper.getReplyerId(reply.getReplyId());
        } else
            //回复的评论，从评论表里查
            toCustomerId = this.detailMapper.getCommenterId(reply.getComId());
        if (toCustomerId == null) return;
        //查询当前用户的名称，如果是置业顾问，要从置业顾问表里查
        String currentUserName = null;
        if (isSellMan) {
            currentUserName = this.detailMapper.getSellManNameByid(currentUserId);
            if (currentUserName == null) return;
            currentUserName = "置业顾问" + currentUserName;
        } else {
            currentUserName = this.detailMapper.getUserNameByid(currentUserId);
            if (currentUserName == null) return;
        }
        //拼接消息，调用用户服务发送消息
        String title = "您有的评论有新的回复";
        String content = currentUserName + "回复了您的评论,点我查看!";
        Integer buildingId = reply.getBuildingId();
        String url = customerServiceUrl + "/sendCommentReplyMsg";
        Map<String, Object> m = new HashMap<>();
        m.put("toCustomerId", toCustomerId);
        m.put("content", content);
        m.put("title", title);
        m.put("buildingId", buildingId);
        String data = JSON.toJSONString(m);
        String res = doPostSendMsg(data, url);
        log.info("回复评论推送消息结果:" + res);
    }

    /**
     * 封装http请求发送post,返回接口的结果
     */
    private String doPostSendMsg(String jsonData, String url) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> entity = new HttpEntity<String>(jsonData, headers);
        String json = ribonTemplate.postForObject(url, entity, String.class);
        return json;
    }


    @Override
    public Object praiseComment(Integer commentId, Integer iHasPraise) {
        int currentUserId = CurrentUser.getCurrentUserId();
        if (commentId == null)
            return ResultUtil.fail("点赞失败");
        if (iHasPraise == null)
            return ResultUtil.fail("点赞失败");
        BuildingCommentPraiseBean praise = new BuildingCommentPraiseBean();
        praise.setCommentId(commentId);
        praise.setCreateTime(new Date());
        praise.setPraiserId(currentUserId);
        if (iHasPraise > 0) {
            //取消点赞，直接删了
            this.detailMapper.deletePraiseData(praise);
            return ResultUtil.ok();
        }
        //执行点赞，添加
        try {
            int index = this.detailMapper.addPraiseData(praise);
            if (index > 0) {
                //消息通知
                this.commonService.runInThreadPool(() -> {
                    commentPraiseMsg(commentId, currentUserId);
                });
                log.info("点赞成功");
            }
            return ResultUtil.ok();
        } catch (Exception e) {
            return ResultUtil.fail("您已经点赞过了");
        }

    }


    private void commentPraiseMsg(Integer commentId, Integer currentUserId) {

        //查询评论人的id，评论的楼盘
        BuildingCommentBean comment = this.detailMapper.getCommentById(commentId);
        if (comment == null)
            return;
        int toCustomerId = comment.getCustomerId();
        int buildingId = comment.getBuildingId();
        //查询点赞者的名字
        String name = this.detailMapper.getUserNameByid(currentUserId);
        String content = name + "给您的评论点赞了,点我查看!";
        String title = "您的评论获赞了";
        Map<String, Object> m = new HashMap<>();
        m.put("toCustomerId", toCustomerId);
        m.put("content", content);
        m.put("title", title);
        m.put("buildingId", buildingId);
        String url = customerServiceUrl + "/sendCommentPraiseMsg";
        String data = JSON.toJSONString(m);
        String res = doPostSendMsg(data, url);
        log.info("点赞评论推送消息结果:" + res);
    }


    @Override
    public Object getCommentsAndOthersInfo(Integer buildingId) {
//		if(buildingId==null)
//			return ResultUtil.fail("楼盘ID为空");
//		//查询评论及点赞信息
//		List<BuildingCommentBean> cms = this.detailMapper
//				.getBuildingDetailComments(buildingId,CurrentUser.getCurrentUserId());
//				//查询，默认的加群评论
//		BuildingCommentBean defComent = this.detailMapper
//				.getDefaultComment(buildingId,CurrentUser.getCurrentUserId());
//		List<BuildingCommentBean> res = new ArrayList<>();
//		res.add(defComent);
//		res.addAll(cms);
//		//处理如果是置业顾问的评论
//		res.forEach(r->{
//			if(r==null)
//				return;
//			if(!StringUtils.isEmpty(r.getCname()))
//				r.setCustomerName(r.getCname());
//		});
//		//查询这三条评论的所有回复以及回复的回复
//		if(res.size()>0) {
//			List<BuildingCommentReply> replys = this.detailMapper.getCommentReply(res);
//			if(replys.size()>0)
//				formatCommentAndReplys(res, replys);
//		}
//
//		//查询竞品，两条
//		List<BuildingCompetitor> bcs = this.cacheService.getBuildingCompetitors(buildingId);
//		if(bcs==null) {
//			bcs=this.detailMapper.getCompetitor(buildingId);
//			this.cacheService.setBuildingDetailCompetitor(buildingId, bcs);
//		}
//		//格式化竞品销售状态
//		for(BuildingCompetitor bc:bcs) {
//			String ss = this.getSellState(bc.getSellStatus());
//			bc.setSaleState(ss);
//		}
//		//查询资讯
//		List<BuildingInformationBean> imf  = this.cacheService.getBuildingDetaiInformation(buildingId);
//		if(imf==null) {
//			imf = this.detailMapper.getBuildingInformation(buildingId);
//			this.cacheService.setBuildingDetailInfomation(buildingId, imf);
//		}
//
//		//查询优秀置业顾问
//		List<SaleManBean> smb = this.cacheService.getBuildingDetailSaleMan(buildingId);
//		if(smb==null||smb.size()==0) {
//			smb = this.detailMapper.getSaleMan(buildingId);
//			if(smb.size()==0)
//				this.cacheService.setBuildingDetailSaleMan(buildingId, new ArrayList<>());
//			else
//				this.cacheService.setBuildingDetailSaleMan(buildingId, smb);
//		}
//		Map<String,Object>  m = new HashMap<>();
//		m.put("comment", res);
//		m.put("otherBuilding", bcs.size()==0?null:bcs);
//		m.put("information", imf.size()==0?null:imf);
//		m.put("saleMan", smb.size()==0?null:smb);
//		return ResultUtil.ok(m);
        return null;
    }


    @Override
    public Object notifyBuildingMsg(Boolean isNotify, Integer buildingId, Integer customerId) {
        if (isNotify == null)
            return ResultUtil.fail("参数错误");
        if (buildingId == null)
            return ResultUtil.fail("参数错误");
        BuildingNotifyRecord r = new BuildingNotifyRecord();
        r.setBuildingId(buildingId);
        r.setCustomerId(customerId);
        try {
            if (!isNotify) { //未提醒则提醒
                this.detailMapper.addNotifyRecord(r);
                return ResultUtil.ok(true);
            }
        } catch (Exception e) {
            return ResultUtil.fail("已经添加提醒记录了");
        }
        //如果提醒了则删除提醒记录
        this.detailMapper.deleteNotifyRecord(r);
        return ResultUtil.ok(false);
    }

    /**
     * orderId  预售i正好
     */
    public Object getProjectInfo(String orderId) {
        if (StringUtils.isEmpty(orderId))
            return ResultUtil.fail("预售证号缺失");
        ProjectInfo x = this.detailMapper.getProjectInfo(orderId);
        if (x == null)
            return ResultUtil.fail("预售信息不存在");
        return ResultUtil.ok(x);
    }

    /**
     * 楼盘动态
     *
     * @return
     */
    @Override
    public Object getBuildingDyn(Integer buildingId, Integer page, Integer size) {
        if (page == null || page < 1)
            page = 1;
        List<BuildingDynamic> dyns = detailMapper.getBuildingDyn(buildingId, (page - 1) * 10, 10);
        Integer total = 0;
        if (dyns != null && dyns.size() > 0) {
            dyns.forEach(this::dealImgAndDate);
            total = detailMapper.getBuildingDynTotal(buildingId);
        }
        Map<String, Object> m = new HashMap<>();
        m.put("total", total);
        m.put("rows", dyns);
        return ResultUtil.ok(m);
    }

    private void dealImgAndDate(BuildingDynamic d) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String img = d.getImgStr();
        if (!StringUtils.isEmpty(img)) {
            d.setImgs(img.split(","));
            d.setImgStr(null);
        } else
            d.setImgs(new String[0]);
        d.setShowTime(sdf.format(d.getCreateDate()));
        d.setCreateDate(null);
    }

    /**
     * 生成楼盘详情海报
     *
     * @return
     */
    @Override
    public Object createBuildingDetailBillBase64(Integer buildingId) {
        // 缓存里没有封面图，直接走数据库了
        BuildingBasicBean basic = detailMapper.getBuildingBillBean(buildingId);
        if (basic == null)
            return ResultUtil.fail("无楼盘信息");
        byte[] qrCode;
        try {
            qrCode = getBuildingBillQRcode(basic);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取楼盘详情海报二维码失败", e);
            return ResultUtil.fail("获取海报失败");
        }
        if (qrCode == null || qrCode.length == 0) {
            log.error("获取楼盘详情海报二维码失败");
            return ResultUtil.fail("获取海报失败");
        }

        try {
            String base64 = generateBill(basic, qrCode);
//			GenerateImage(base64);
            return ResultUtil.ok(null, base64);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("生成楼盘详情海报失败");
            return ResultUtil.fail("获取海报失败");
        }
    }

    private void GenerateImage(String base64) {
        BASE64Decoder d = new BASE64Decoder();
        try {
            byte[] bs = d.decodeBuffer(base64);
            FileOutputStream os = new FileOutputStream("D:\\text\\qr.png");
            os.write(bs);
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private String generateBill(BuildingBasicBean basic, byte[] qrCode) throws Exception {
        int x = 750;
        int y = 1334;
        //创建底板画布
        BufferedImage billImgBuffer = new BufferedImage(x, y, BufferedImage.TYPE_INT_RGB);// RGB形式
        Graphics2D bill2d = billImgBuffer.createGraphics();
        bill2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);//抗锯齿
        bill2d.setBackground(Color.WHITE);//设置背景为白色
        bill2d.clearRect(0, 0, 800, 1500);//通过使用当前绘图表面的背景色进行填充来清除指定的矩形
        // 绘制背景图
        drawBackGroundImg(bill2d, x, y);
        // 绘制线上售楼部提醒字样
        drawRemindFont(bill2d);
        // 绘制楼盘名称
        drawBuildingName(bill2d, basic);
        // 绘制封面图
        drawCoverImg(basic, bill2d);
        // 绘制价格等
        drawPrice(basic, bill2d);
        // 绘制区域街道
        drawRegion(basic, bill2d);
        // 绘制物业等信息
        drawProperty(basic, bill2d);
        //绘画小程序二维码
        drawQrCode(qrCode, bill2d);
        //结束绘制,转成byte[]数组并格式化为base64
        bill2d.dispose();
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ImageIO.write(billImgBuffer, "png", byteOut);
        byte[] b = byteOut.toByteArray();
        return new String(Base64.getEncoder().encode(b));
    }

    private void drawRemindFont(Graphics2D bill2d) {
        Font font = new Font("黑体", Font.BOLD, 35);
        Color c = new Color(17, 17, 17);
        bill2d.setColor(c);
        bill2d.setFont(font);//设置画笔
        bill2d.drawString("线上售楼部开启呢", 230, 116);
    }

    private void drawProperty(BuildingBasicBean basic, Graphics2D bill2d) {
        Font font = new Font("黑体", Font.PLAIN, 28);
        Color c = new Color(17, 17, 17);
        bill2d.setColor(c);
        bill2d.setFont(font);//设置画笔
        bill2d.drawString("物业类型：" + getPropType(basic.getPropType()), 88, 793);
        String brand = basic.getBrandName();
        brand = StringUtils.isEmpty(brand) ? "" : (brand.length() > 16 ? brand.substring(0, 16) + "..." : brand);
        bill2d.drawString("开发商：" + brand, 88, 853);
        bill2d.drawString("占地面积：" + (StringUtils.isEmpty(basic.getSpace()) ? "" : basic.getSpace()), 88, 913);
        bill2d.drawString("物业费：" + (StringUtils.isEmpty(basic.getPropCost()) ? "" : basic.getPropCost()), 88, 973);
        bill2d.drawString("交房时间：" + (StringUtils.isEmpty(basic.getCompleteTime()) ? "" : basic.getCompleteTime()), 88, 1033);
    }

    private void drawRegion(BuildingBasicBean basic, Graphics2D bill2d) {
        Font font = new Font("黑体", Font.PLAIN, 28);
        Color c = new Color(17, 17, 17);
        bill2d.setColor(c);
        bill2d.setFont(font);//设置画笔
        String region = basic.getRegion() + (StringUtils.isEmpty(basic.getStreet()) ? "" : "-" + basic.getStreet());
        String sellState = getSellState(basic.getSellStatus());
        bill2d.drawString(region + " | " + sellState, 88, 628);
        if (!StringUtils.isEmpty(basic.getAddress()))
            bill2d.drawString(basic.getAddress().length() > 21 ? basic.getAddress().substring(0, 21) + "..." : basic.getAddress(), 120, 683);
    }

    private void drawPrice(BuildingBasicBean basic, Graphics2D bill2d) {
        Font font = new Font("黑体", Font.BOLD, 38);
        Color c = new Color(255, 52, 68);
        bill2d.setColor(c);
        bill2d.setFont(font);//设置画笔
        String p = basic.getPrice();
        if (StringUtils.isEmpty(p))
            p = "价格待定";
        else {
            String[] price = p.split("\\+");
            p = price[0];
        }
        // 设置字体左右间距
        bill2d.drawString(p, 89, 571);
    }

    private void drawCoverImg(BuildingBasicBean basic, Graphics2D bill2d) throws Exception {
        String url = basic.getCoverImg();
        if (StringUtils.isEmpty(url))
            return;
        byte[] bs = restTemplate.getForObject(url, byte[].class);
        BufferedImage qrCodeImg = new BufferedImage(450, 248, BufferedImage.TYPE_INT_RGB);
        Graphics2D qr2d = qrCodeImg.createGraphics();
        ByteArrayInputStream bin = new ByteArrayInputStream(bs);
        //将二维码图片绘制在画布上,按照画布进行缩放
        qr2d.drawImage(ImageIO.read(bin), 0, 0, 450, 248, null);
        qr2d.dispose();
        //将二维码绘制到背景图上下文
        bill2d.drawImage(qrCodeImg, 150, 241, 450, 248, null);
    }


    private void drawBuildingName(Graphics2D bill2d, BuildingBasicBean basic) {
        Font font = new Font("黑体", Font.BOLD, 46);
        Color c = new Color(17, 17, 17);
        bill2d.setColor(c);
        bill2d.setFont(font);//设置画笔
        // 设置字体左右间距
        Map<String, Object> x = getX(basic.getName());
        bill2d.drawString((String) x.get("name"), (int) x.get("x"), 177);
    }

    private Map<String, Object> getX(String name) {
        int length = name.length();
        if (length > 12) {
            length = 12;
            name = name.substring(0, 12) + "...";
        }
		/*三个字300 四个字278 五个字252 六个字228 七个字202
		八个字178 九个字152 十个字126 十一个字100 十二76*/
        int[] xSpace = new int[]{300, 300, 300, 278, 252, 228, 202, 178, 152, 126, 100, 76};
        Map<String, Object> m = new HashMap<>();
        m.put("name", name);
        m.put("x", xSpace[length - 1]);
        return m;
    }


    private void drawBackGroundImg(Graphics2D bill2d, int x, int y) throws Exception {
        // 表示这段文字在图片上的位置(x,y) .第一个是你设置的内容.问题宽度是450px
        BufferedImage bgImg = ImageIO.read(new URL(buildingBackGroundUrl));
        bill2d.drawImage(bgImg, 0, 0, x, y, null);
    }

    private void drawQrCode(byte[] qrCode, Graphics2D bill2d) throws Exception {
        //创建二维码的指定大小画布
        BufferedImage qrCodeImg = new BufferedImage(164, 154, BufferedImage.TYPE_INT_RGB);
        Graphics2D qr2d = qrCodeImg.createGraphics();
        ByteArrayInputStream bin = new ByteArrayInputStream(qrCode);
        //将二维码图片绘制在画布上,按照画布进行缩放
        qr2d.drawImage(ImageIO.read(bin), 0, 0, 164, 154, null);
        qr2d.dispose();
        //将二维码绘制到背景图上下文
        bill2d.drawImage(qrCodeImg, 124, 1112, 164, 154, null);
    }

    private byte[] getBuildingBillQRcode(BuildingBasicBean basic) {
        String url = QR_IMG_HOST + wxAcctkCacheService.getMiniprogramAcctk();
        Integer sid = CurrentUser.getCurrentUserId();
        String param = "bid=" + basic.getId() + (pageService.isSellMan(sid) ? "&sid=" + sid : "");
        Map<String, String> m = new HashMap<>();
        m.put("page", "pages/house/details_comment/main");
        m.put("scene", param);
        HttpHeaders headers = new HttpHeaders();
        //设置请求媒体数据类型
        headers.setContentType(MediaType.APPLICATION_JSON);
        String json = JSON.toJSONString(m);
        HttpEntity<String> formEntity = new HttpEntity<>(json, headers);
        ResponseEntity<byte[]> res = restTemplate.postForEntity(url, formEntity, byte[].class);
        byte[] x = res.getBody();
        return x;
    }

    @Override
    public Object getDiscounts(Integer buildingId, Integer page) {
        if (page == null || page < 1)
            page = 1;
        List<BuildingDiscount> bds = detailMapper.getDiscounts((page - 1) * 10, 10, buildingId);
        if (bds != null && bds.size() > 0) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            bds.forEach(b -> {
                b.setShowTime(sdf.format(b.getCreateTime()));
                b.setCreateTime(null);
                if (!StringUtils.isEmpty(b.getImg())) {
                    b.setImgs(b.getImg().split(","));
                    b.setImg(null);
                }
            });
        }
        Integer total = detailMapper.getDiscountTotal(buildingId);
        Map<String, Object> m = new HashMap<>();
        m.put("total", total);
        m.put("rows", bds);
        return ResultUtil.ok(m);
    }
}
